package com.kjc.demo.netty.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Setter
@Getter
public final class Client {
	
	private String host;
	
	private Integer port;
	
	private SocketChannel socketChannel;
	
	EventLoopGroup group = new NioEventLoopGroup();
	
	public Client(String host, Integer port) {
		this.host = host;
		this.port = port;
	}
	
	public void send() {
		this.socketChannel.writeAndFlush("00 01 00 00 00 06 01 01 00 02 00 08");
	}
	
	public void start() {
//		EventLoopGroup group = new NioEventLoopGroup();
		
		try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                // 设置通道
                .channel(NioSocketChannel.class)
                // 日志处理格式
                .handler(new LoggingHandler(LogLevel.INFO))
                // 禁用nagle算法
                .option(ChannelOption.TCP_NODELAY, true)
                // 保持长连接
                .option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
                // 流程处理
                .handler(new ClientInitializer());
            // start to channel
            ChannelFuture future = bootstrap.connect(host, port).sync();
            future.addListener((ChannelFutureListener) future1 -> {
                if (future1.isSuccess()) {
                    log.info("**********************嵌套netty client服务连接成功**********************");
                } else {
                    log.warn("**********************服务连接失败，20s后开始重新连接服务器**********************");
                    // 20s后重新连接
                    future1.channel().eventLoop().schedule(() -> this.start(), 20, TimeUnit.SECONDS);
                }
            });
            socketChannel = (SocketChannel) future.channel();
        } catch (Exception e) {
            log.error("connection error", e.getMessage(), e);
            if(socketChannel != null){
                socketChannel.close();
            }
            group.shutdownGracefully();
        }
		
	}
	
	public void destroy() {
		if(socketChannel != null){
            socketChannel.close();
        }
		group.shutdownGracefully();
	}
    public static void main(String[] args) throws Exception {
    	
    	new StringDecoder(Charset.forName("GBK"));
    	
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ClientInitializer());
            Channel ch = b.connect("127.0.0.1",30502).sync().channel();


            ChannelFuture lastWriteFuture = null;
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            for (;;) {
                String line = in.readLine();
                if (line == null) {
                    break;
                }

                // Sends the received line to the server.
                lastWriteFuture = ch.writeAndFlush(line + "\r\n");

                // If user typed the 'bye' command, wait until the server closes
                // the connection.
                if ("bye".equals(line.toLowerCase())) {
                    ch.closeFuture().sync();
                    break;
                }
            }

            // Wait until all messages are flushed before closing the channel.
            if (lastWriteFuture != null) {
                lastWriteFuture.sync();
            }
        } finally {
            group.shutdownGracefully();
        }
    }
}
